package pku;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * 这是一个消息队列的内存实现
 */
public class MessageStoreOut {

    static FileOutputStream os = null;
    static FileChannel fo = null;
    static ByteBuffer buffer = null;

    static {
        try {

            os = new FileOutputStream("./data/a.txt");
            fo = os.getChannel();
            buffer = ByteBuffer.allocate(4096 * 2);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static final MessageStoreOut store = new MessageStoreOut();

    // 消息存储
    HashMap<String, ArrayList<ByteMessage>> msgs = new HashMap<>();

    // 加锁保证线程安全

    /**
     * @param msg
     * @param
     */
    public synchronized void push(ByteMessage msg) {
        if (msg == null) {
            return;
        }
        String topic = msg.headers().getString(MessageHeader.TOPIC);
        try {

//			HashMap<String, Object> hm = msg.headers().getMap();
            HashMap<String, Object> hm = new HashMap<>();
            int len = msg.getBody().length + topic.getBytes().length + 3;
            for (String k : hm.keySet()) {
                if (MessageHeader.TOPIC.equals(k)) {
                    continue;
                }
                int lenHeader = k.getBytes().length + hm.get(k).toString().getBytes().length + 3;
                len += lenHeader;
            }

            byte[] byteTotal = new byte[len];

            byteTotal[0] = (byte) (len - 1);

            byteTotal[1] = (byte) topic.getBytes().length;
            byte[] tb = topic.getBytes();
            System.arraycopy(tb, 0, byteTotal, 2, tb.length);

            byteTotal[tb.length + 2] = (byte) msg.getBody().length;
            byte[] bo = msg.getBody();
            System.arraycopy(bo, 0, byteTotal, tb.length + 3, bo.length);

            int length = tb.length + 2 + bo.length;
            for (String key : hm.keySet()) {
                if (MessageHeader.TOPIC.equals(key)) {
                    continue;
                }

                Object obj = hm.get(key);

                byteTotal[++length] = (byte) key.getBytes().length;
                byte[] kb = key.getBytes();
                System.arraycopy(kb, 0, byteTotal, ++length, kb.length);
                length = length + kb.length - 1;

                int type = type(obj);
                byteTotal[++length] = (byte) type;

                byteTotal[++length] = (byte) obj.toString().getBytes().length;

                byte[] hv = obj.toString().getBytes();
                System.arraycopy(hv, 0, byteTotal, ++length, hv.length);
                length = length + hv.length - 1;
            }
            buffer.clear();

            buffer.put(byteTotal);

            buffer.flip();

            fo.write(buffer);
            buffer.clear();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private int type(Object obj) {

        if (obj instanceof Integer) {
            return 4;
        } else if (obj instanceof Long) {
            return 1;
        } else if (obj instanceof Double) {
            return 2;
        } else if (obj instanceof String) {
            return 3;
        }
        return 3;
    }
}
